using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Rogan.Data
{
	public class ExpressionTranslater
	{
		internal const string SQL_SELECT = " SELECT ";
		internal const string SQL_FROM = " FROM ";
		internal const string SQL_DISTINCT = " DISTINCT ";
		internal const string SQL_TOP = " TOP ";
		internal const string SQL_WHERE = " WHERE ";
		internal const string SQL_ORDERBY = " ORDER BY ";
		internal const string SQL_ORDERBY_ASC = " ASC ";
		internal const string SQL_ORDERBY_DESC = " DESC ";
		internal const string SQL_GROUPBY = " GROUP BY ";
		internal const string SQL_HAVING = " HAVING ";
		internal const string SQL_JOIN_INNER = " INNER JOIN ";
		internal const string SQL_JOIN_LEFT = " LEFT JOIN ";
		internal const string SQL_JOIN_RIGHT = " RIGHT JOIN ";
		internal const string SQL_JOIN_CROSS = " CROSS JOIN ";
		internal const string SQL_JOIN_ON = " ON ";
		internal const string SQL_UPDDATE = " UPDATE ";
		internal const string SQL_INSERTINTO = " INSERT INTO ";
		internal const string SQL_INSERT_VALUES = " VALUES ";
		internal const string SQL_DELETEFROM = " DELETE FROM";
		internal const string SQL_UPDATE_SET = " SET ";
		private int paramCounter;
		public DbProvider DbProvider
		{
			get;
			private set;
		}
		public EntityQueryExpression Expression
		{
			get;
			private set;
		}
		public List<QueryParameter> Params
		{
			get;
			private set;
		}
		public string CommandText
		{
			get;
			private set;
		}
		internal void SetCommandText(string commandText)
		{
			CommandText = commandText;
		}
		public ExpressionTranslater() : this(null, null)
		{
		}
		public ExpressionTranslater(DbProvider dbProvider) : this(dbProvider, null)
		{
		}
		public ExpressionTranslater(DbProvider dbProvider, EntityQueryExpression exp)
		{
			DbProvider = dbProvider;
			Params = new List<QueryParameter>();
			Expression = exp;
		}
		public void Translate()
		{
			DbProvider.PrepareTranslater(this);
			CommandText = TranslateEntityQuery(Expression);
			DbProvider.AdjustTranslater(this);
		}
		public string TranslateEntityQuery(EntityQueryExpression exp)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(TranslateSelect(exp));
			stringBuilder.Append(" FROM ");
			stringBuilder.Append(DbProvider.BuildTableName(exp.From.GetName()));
			if (exp.Joins != null)
			{
				foreach (JoinExpression current in exp.Joins)
				{
					stringBuilder.Append(TranslateJoin(current));
				}
			}
			if (exp.Where != null)
			{
				stringBuilder.Append(" WHERE ");
				stringBuilder.Append(TranslateWhere(exp.Where));
			}
			if (exp.IsOrderBy)
			{
				stringBuilder.Append(TranslateOrderyByList(exp.OrderByList));
			}
			if (exp.GroupBy != null)
			{
				stringBuilder.Append(TranslateGroupBy(exp.GroupBy));
			}
			return stringBuilder.ToString();
		}
		private string CreateParmName()
		{
			return "p" + ++paramCounter;
		}
		public string TranslateWhere(WhereExpression exp)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (exp.IsSingle)
			{
				if (exp.Operator == QueryOperator.BitwiseNOT && exp.Quote != null && exp.Quote.Operator == QueryOperator.In)
				{
					return TranslateWhere(WhereExpression.Create(exp.Quote.LeftField, exp.Quote.Value, QueryOperator.NotIn));
				}
				if (exp.LeftField != null && exp.RightField != null)
				{
					stringBuilder.Append(exp.LeftField.FieldNameWithTable);
					stringBuilder.Append(DataHelper.GetOperatorQueryText(exp.Operator));
					stringBuilder.Append(exp.RightField.FieldNameWithTable);
				}
				else
				{
					if (exp.LeftField != null)
					{
						stringBuilder.Append(exp.LeftField.FieldNameWithTable);
						stringBuilder.Append(DataHelper.GetOperatorQueryText(exp.Operator));
						if (exp.SubExpression != null)
						{
							stringBuilder.Append("(" + TranslateEntityQuery(exp.SubExpression) + ")");
						}
						else
						{
							if (exp.Operator == QueryOperator.In || exp.Operator == QueryOperator.NotIn)
							{
								stringBuilder.Append("(");
								if (exp.Value != null)
								{
									bool flag = false;
									foreach (object current in (IEnumerable)exp.Value)
									{
										QueryParameter queryParameter = new QueryParameter(CreateParmName(), current);
										Params.Add(queryParameter);
										if (flag)
										{
											stringBuilder.Append(",");
										}
										stringBuilder.Append(queryParameter.Name);
										flag = true;
									}
								}
								stringBuilder.Append(")");
							}
							else
							{
								if (exp.Operator != QueryOperator.IsNotNULL && exp.Operator != QueryOperator.IsNULL)
								{
									QueryParameter queryParameter2 = new QueryParameter(CreateParmName(), exp.Value);
									Params.Add(queryParameter2);
									stringBuilder.Append(queryParameter2.Name);
								}
							}
						}
					}
					else
					{
						if (exp.RightField != null)
						{
							QueryParameter queryParameter3 = new QueryParameter(CreateParmName(), exp.Value);
							stringBuilder.Append(queryParameter3.Name);
							stringBuilder.Append(DataHelper.GetOperatorQueryText(exp.Operator));
							stringBuilder.Append(exp.RightField.FieldNameWithTable);
							Params.Add(queryParameter3);
						}
					}
				}
			}
			else
			{
				stringBuilder.Append("(" + TranslateWhere(exp.Left) + ")");
				stringBuilder.Append(DataHelper.GetOperatorQueryText(exp.Operator));
				stringBuilder.Append("(" + TranslateWhere(exp.Right) + ")");
			}
			if (stringBuilder.Length < 8)
			{
				return "";
			}
			return stringBuilder.ToString();
		}
		public string TranslateSelect(EntityQueryExpression exp)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(" SELECT ");
			if (exp.IsDistinct.HasValue && exp.IsDistinct.Value)
			{
				stringBuilder.Append(" DISTINCT ");
			}
			if (exp == Expression)
			{
				stringBuilder.Append(DbProvider.GetSQLSelectTopClip(this));
			}
			List<Field> selectFields = exp.SelectFields;
			bool flag = false;
			foreach (Field current in selectFields)
			{
				if (flag)
				{
					stringBuilder.Append(",");
				}
				stringBuilder.Append(current.FullName);
				flag = true;
			}
			if (!flag)
			{
				stringBuilder.Append(" *");
			}
			return stringBuilder.ToString();
		}
		public string TranslateJoin(JoinExpression exp)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (exp.JoinType == JoinType.InnerJoin)
			{
				stringBuilder.Append(" INNER JOIN ");
			}
			else
			{
				if (exp.JoinType == JoinType.LeftJoin)
				{
					stringBuilder.Append(" LEFT JOIN ");
				}
				else
				{
					if (exp.JoinType == JoinType.CrossJoin)
					{
						stringBuilder.Append(" CROSS JOIN ");
					}
					else
					{
						stringBuilder.Append(" RIGHT JOIN ");
					}
				}
			}
			stringBuilder.Append("{0}" + exp.Entity.GetName() + "{1} ON ");
			stringBuilder.Append(TranslateWhere(exp.Where));
			return stringBuilder.ToString();
		}
		public string TranslateOrderyBy(OrderByExpression exp)
		{
			if (exp.Field == null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(exp.Field.FieldNameWithTable);
			stringBuilder.Append(" " + ((exp.Direction == OrderByDirection.Asc) ? " ASC " : " DESC "));
			return stringBuilder.ToString();
		}
		public string TranslateGroupBy(GroupByExpression exp)
		{
			StringBuilder stringBuilder = new StringBuilder();
			IList<Field> fields = exp.Fields;
			if (fields == null || fields.Count == 0)
			{
				return "";
			}
			stringBuilder.Append(" GROUP BY ");
			bool flag = false;
			foreach (Field current in fields)
			{
				if (flag)
				{
					stringBuilder.Append(",");
				}
				stringBuilder.Append(current.FieldNameWithTable);
				flag = true;
			}
			if (exp.Having != null)
			{
				stringBuilder.Append(" HAVING ");
				stringBuilder.Append(TranslateWhere(exp.Having));
			}
			return stringBuilder.ToString();
		}
		public string TranslateOrderyByList(IList<OrderByExpression> orderbys)
		{
			return TranslateOrderyByList(orderbys, false);
		}
		public string TranslateOrderyByList(IList<OrderByExpression> orderbys, bool isReverse)
		{
			if (orderbys == null || orderbys.Count == 0)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(" ORDER BY ");
			bool flag = false;
			foreach (OrderByExpression current in orderbys)
			{
				if (flag)
				{
					stringBuilder.Append(",");
				}
				if (!isReverse)
				{
					stringBuilder.Append(TranslateOrderyBy(current));
				}
				else
				{
					stringBuilder.Append(TranslateOrderyBy(current.Reverse()));
				}
				flag = true;
			}
			return stringBuilder.ToString();
		}
	}
}
